package simpledb.storage;

import simpledb.common.DbException;
import simpledb.transaction.TransactionAbortedException;

import java.util.NoSuchElementException;

/**
 * AbstractDbFileIterator 是一个抽象类，用于简化 DbFileIterator 的实现。
 * 它封装了 hasNext() 和 next() 方法的基本逻辑，
 * 子类只需要实现 readNext() 方法即可。
 */
public abstract class AbstractDbFileIterator implements DbFileIterator {

    // 缓存下一个可用的 Tuple，避免重复调用 readNext()
    private Tuple next = null;

    /**
     * 判断是否还有下一个元组可供读取。
     *
     * @return 如果有下一个元组则返回 true，否则返回 false
     * @throws DbException 数据库操作异常
     * @throws TransactionAbortedException 当前事务被中断
     */
    public boolean hasNext() throws DbException, TransactionAbortedException {
        if (next == null)
            next = readNext(); // 尝试预加载下一个元组
        return next != null;
    }

    /**
     * 获取下一个元组。
     *
     * @return 下一个元组
     * @throws DbException 数据库操作异常
     * @throws TransactionAbortedException 当前事务被中断
     * @throws NoSuchElementException 当没有更多元组时抛出此异常
     */
    public Tuple next() throws DbException, TransactionAbortedException, NoSuchElementException {
        if (next == null) {
            next = readNext(); // 尝试读取下一个元组
            if (next == null)
                throw new NoSuchElementException(); // 没有更多数据
        }

        Tuple result = next; // 返回当前缓存的元组
        next = null; // 清空缓存，为下一次读取做准备
        return result;
    }

    /**
     * 关闭迭代器，释放资源。
     * 如果子类重写该方法，应调用 super.close()。
     */
    public void close() {
        next = null; // 清除缓存的下一个元组
    }

    /**
     * 从底层数据源读取下一个元组。
     * 子类必须实现该方法以提供具体的读取逻辑。
     *
     * @return 下一个元组，如果没有更多数据则返回 null
     * @throws DbException 数据库操作异常
     * @throws TransactionAbortedException 当前事务被中断
     */
    protected abstract Tuple readNext() throws DbException, TransactionAbortedException;
}
